package cn.itedus.lottery.domain.strategy.service.algorithm.impl;

import cn.itedus.lottery.domain.strategy.service.algorithm.BaseAlgorithm;
import org.springframework.stereotype.Component;

import java.security.SecureRandom;
import java.util.List;

/**
 * 【推荐】单项随机概率抽奖，抽到一个已经排掉的奖品则未中奖
 */
@Component("singleRateRandomDrawAlgorithm")  //不指定name也行，默认 Bean 名称为类名首字母小写
public class SingleRateRandomDrawAlgorithm extends BaseAlgorithm {
    /**
     * SecureRandom 生成随机数，索引到对应的奖品信息，如果是空的返回未中奖
     *  *在initRateTuple中初始化了rateTupleMap字典（strategyId -> rateTuple）和awardRateInfoMap字典（strategyId -> [awardId->begin、awardId->end]）
     *  * 比如策略id为1,这个策略要求一等奖概率0.2,二等奖概率0.3,三等奖概率0.5 放入和awardRateInfoMap字典
     *  * 概率散列这个列表包含128个元素,其中有20个存储一等奖的奖品id,30个存储二等奖的奖品id,50个存储三等奖的奖品id,放入rateTupleMap字典
     *
     * @param strategyId 策略ID
     * @param excludeAwardIds 排除掉已经不能作为抽奖的奖品ID，留给风控和空库存使用
     * @return
     */
    @Override
    public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
        // 获取策略对应的元组
        String[] rateTuple = super.rateTupleMap.get(strategyId);
        assert rateTuple != null;

        // 随机索引
        int randomVal =  this.generateSecureRandomIntCode(100);  //[1,100]
        int idx = super.hashIdx(randomVal);  //必然会存在值，因为初始化的时候就是使用[1,100]进行hash的

        // 返回结果
        String awardId = rateTuple[idx];

        // 如果中奖ID命中排除奖品列表，则返回NULL
        if (excludeAwardIds.contains(awardId)) {
            return null;
        }

        return awardId;
    }
}
